from xml.dom.minidom import parse, parseString
import networkx as nx
from task import Task, Host
from operator import itemgetter, attrgetter
from  math import ceil

import matplotlib.pyplot as plt

NODE_SPEED=70
NODE_NET = 10
class FCP:
	def __init__(self, hosts, tasks, workflow):
		self.tasks = parse(tasks)
		self.loadHosts(hosts)
		self.loadWorkflow(workflow)
		self.createDuplicates();
		#if not nx.is_directed_acyclic_graph(taskGraph):
		#	raise Exception("Not an acyclic graph")
	
	def getTaskFromName(self, name):
		ret = Task(name, 0,0, None)
		xml = self.tasks.getElementsByTagName('tasks')[0]
		for node in xml.getElementsByTagName('task'):
			if node.getElementsByTagName('name')[0].firstChild.nodeValue == name:
				ret.proc = node.getElementsByTagName('proc')[0].firstChild.nodeValue
				ret.net = node.getElementsByTagName('net')[0].firstChild.nodeValue
				if len(node.getElementsByTagName('pinned')) != 0:
					ret.pinned  = node.getElementsByTagName('pinned')[0].firstChild.nodeValue
		return ret
	
	def loadHosts(self, hosts):
		self.hosts = []
		xml = parse(hosts)
		xml = xml.getElementsByTagName('hosts')[0]
		for node in xml.getElementsByTagName('host'):
			host = Host(node.getElementsByTagName('name')[0].firstChild.nodeValue, \
			node.getElementsByTagName('ip')[0].firstChild.nodeValue, \
			node.getElementsByTagName('proc')[0].firstChild.nodeValue, \
			node.getElementsByTagName('net')[0].firstChild.nodeValue)
			self.hosts.append(host)
	
	def loadWorkflow(self, workflow):
		self.workflow =nx.DiGraph()
		xml = parse(workflow)
		xml = xml.getElementsByTagName('config')[0]
		self.labels = dict()
		
		for node in xml.getElementsByTagName('node'):
			nodeName = node.getElementsByTagName('name')[0].firstChild.nodeValue
			self.workflow.add_node(nodeName, proc = float(self.getTaskFromName(nodeName).proc))
			self.labels[nodeName] = [nodeName, float(self.getTaskFromName(nodeName).proc)]
		for node in xml.getElementsByTagName('edge'):
			first = node.getElementsByTagName('start')[0].firstChild.nodeValue
			end = node.getElementsByTagName('end')[0].firstChild.nodeValue
			self.workflow.add_edge(first, end, net = float(self.getTaskFromName(first).net))
		
	def drawWorkflow(self):
		nx.draw_graphviz(self.workflow, labels=self.labels,node_size=1000)
		plt.show()
	
	def createDuplicates(self):
		for node in self.workflow.nodes():
			task = self.getTaskFromName(node)
			numTasks = 1;
			if(float(task.proc)/NODE_SPEED > numTasks):
				numTasks = int(ceil(float(task.proc)/NODE_SPEED))
			if(float(task.net)/NODE_NET > numTasks):
				numTasks = int(ceil(float(task.net)/NODE_NET))
			for i in range(1, numTasks):
				newTask = node + " Copy" +str(i)
				self.workflow.add_node(newTask, proc = float(task.proc))
				self.labels[newTask] = [newTask, float(task.proc)]
				for edge in self.workflow.predecessors(node):
					self.workflow.add_edge(edge, newTask,net = float(self.getTaskFromName(edge).net))
				for edge in self.workflow.successors(node):
					self.workflow.add_edge(newTask, edge, net = float(task.net))
			print task.toString()
			print "\ttasks ", numTasks
		
x = FCP('./hosts.xml', './tasks.xml',  './config.xml')
x.drawWorkflow()
